package org.tolk.bench.problems.rubikscube;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

/**
 * bench - an api of popular problems
 * Copyright (C) 2010  Werner van Rensburg
 * <p/>
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * <p/>
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * <p/>
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

public class Face
{
  private HashMap<Position, Integer> faceMap;

  public Face(Integer color)
  {
    faceMap = new HashMap<Position, Integer>();
    setUniformFace(color);
  }

  public void setUniformFace(int color)
  {
    faceMap = new HashMap<Position, Integer>();
    faceMap.put(new Position(0, 0), color);
    faceMap.put(new Position(0, 1), color);
    faceMap.put(new Position(0, 2), color);
    faceMap.put(new Position(1, 0), color);
    faceMap.put(new Position(1, 1), color);
    faceMap.put(new Position(1, 2), color);
    faceMap.put(new Position(2, 0), color);
    faceMap.put(new Position(2, 1), color);
    faceMap.put(new Position(2, 2), color);
    faceMap.put(new Position(3, 0), color);
    faceMap.put(new Position(3, 1), color);
    faceMap.put(new Position(3, 2), color);
  }

  public void setFaceMap(HashMap<Position, Integer> map)
  {
    faceMap = map;
  }

  public HashMap<Position, Integer> getFaceMap()
  {
    return faceMap;
  }

  public void setFaceMapPosition(Position pos, int color)
  {
    faceMap.put(pos, color);
  }

  private void setRow(Integer rowPos, List row) throws IncompleteRowException
  {
    if (row.size() != 3)
    {
      throw new IncompleteRowException();
    }

    for (int col = 0; col < 3; col++)
    {
      Integer color = (Integer) row.get(col);
      faceMap.put(new Position(col, rowPos), color);
    }
  }

  private void setColumnt(Integer colPos, List column) throws IncompleteColumnException
  {
    if (column.size() != 3)
    {
      throw new IncompleteColumnException();
    }

    int row = 0;

    for (Iterator it = column.iterator(); it.hasNext(); row++)
    {
      Integer color = (Integer) it.next();
      faceMap.put(new Position(colPos, row), color);
    }
  }

  private List getRow(int y)
  {
    ArrayList list = new ArrayList<Integer>();
    list.add(faceMap.get(new Position(0, y)));
    list.add(faceMap.get(new Position(1, y)));
    list.add(faceMap.get(new Position(2, y)));
    return list;
  }

  private List getColumn(int x)
  {
    ArrayList list = new ArrayList<Integer>();
    list.add(faceMap.get(new Position(x, 0)));
    list.add(faceMap.get(new Position(x, 1)));
    list.add(faceMap.get(new Position(x, 2)));
    return list;
  }

  private List setRow(List<Integer> rowList, Integer y) throws IncompleteRowException
  {
    List previousRow = getRow(y);
    if (rowList.size() == 3)
    {
      int i = 0;
      for (Integer color : rowList)
      {
        faceMap.put(new Position(i++, y), color);
      }
    }
    else
    {
      throw new IncompleteRowException();
    }
    return previousRow;
  }

  private List setColumn(List<Integer> columnList, Integer x) throws IncompleteColumnException
  {
    List previousColumn = getColumn(x);
    if (columnList.size() == 3)
    {
      int i = 0;
      for (Integer color : columnList)
      {
        faceMap.put(new Position(x, i++), color);
      }
    }
    else
    {
      throw new IncompleteColumnException();
    }
    return previousColumn;
  }

  public List getTopRow()
  {
    return getRow(0);
  }

  public List getMiddleRow()
  {
    return getRow(1);
  }

  public List getBottomRow()
  {
    return getRow(2);
  }

  public List getLeftColunm()
  {
    return getColumn(0);
  }

  public List getMiddleColunm()
  {
    return getColumn(1);
  }

  public List getRightColunm()
  {
    return getColumn(2);
  }

  class IncompleteRowException extends Exception
  {
    public IncompleteRowException()
    {
      super("Incomplete Row");
    }
  }

  class IncompleteColumnException extends Exception
  {
    public IncompleteColumnException()
    {
      super("Incomplete Column");
    }
  }
}
